package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.pro.domain.entity.LabelEntity;
import com.xbongbong.pro.domain.entity.LabelGroupEntity;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemLabelErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.label.pojo.LabelGroupListPojo;
import com.xbongbong.pro.label.pojo.LabelSortPojo;
import com.xbongbong.pro.label.pojo.dto.LabelGroupDeleteDTO;
import com.xbongbong.pro.label.pojo.dto.LabelGroupListDTO;
import com.xbongbong.pro.label.pojo.dto.LabelGroupRepeatDTO;
import com.xbongbong.pro.label.pojo.dto.LabelGroupSaveDTO;
import com.xbongbong.pro.label.pojo.dto.LabelGroupSortDTO;
import com.xbongbong.pro.label.pojo.vo.LabelGroupDeleteVO;
import com.xbongbong.pro.label.pojo.vo.LabelGroupListVO;
import com.xbongbong.pro.label.pojo.vo.LabelGroupRepeatVO;
import com.xbongbong.pro.label.pojo.vo.LabelGroupSaveVO;
import com.xbongbong.pro.label.pojo.vo.LabelGroupSortVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.ext.WorkOrderExplainEntityExt;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.LabelGroupModel;
import com.xbongbong.saas.model.LabelModel;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.service.LabelGroupService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author guohui.zhang
 * @Title:
 * @date 2020/11/39:55
 */
@Service("labelGroupService")
public class LabelGroupServiceImpl implements LabelGroupService {

    private static final Logger LOG = LoggerFactory.getLogger(LabelGroupServiceImpl.class);

    @Resource
    private LabelGroupModel labelGroupModel;
    @Resource
    private LabelModel labelModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private PaasFormModel paasFormModel;

    /**
     * 获取分组列表
     * @param labelGroupListDTO
     * @return
     * @throws XbbException
     */
    @Override
    public LabelGroupListVO getGroupList(LabelGroupListDTO labelGroupListDTO) throws XbbException {
        String corpid = labelGroupListDTO.getCorpid();
        Long appId = labelGroupListDTO.getAppId();
        Long formId = labelGroupListDTO.getFormId();
        LabelGroupListVO labelGroupListVO = new LabelGroupListVO();

        Map<String ,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<LabelGroupEntity> labelGroupEntities = new ArrayList<>();
        // 判断是初始化还是用户自己把分组全部删除了
        param.put("corpid", corpid);
        param.put("appId", appId);
        param.put("formId", formId);
        Integer count = labelGroupModel.getEntitysCount(param);
        if (count >0){
            param.put("orderByStr", " sort desc " );
            param.put("del", DelEnum.NORMAL.getDel());
            labelGroupEntities = labelGroupModel.findEntitys(param);
        } else {
            LabelGroupEntity labelGroupEntity = createDefaultLabelGroup(labelGroupListDTO.getUserId(), corpid, appId, formId);
            labelGroupEntities.add(labelGroupEntity);
        }


        List<LabelGroupListPojo> labelGroupListPojos = new ArrayList<>();
        labelGroupEntities.forEach(item ->{
            LabelGroupListPojo labelGroupListPojo = new LabelGroupListPojo();
            labelGroupListPojo.setId(item.getId());
            labelGroupListPojo.setName(item.getGroupName());
            labelGroupListPojo.setSort(item.getSort());
            labelGroupListPojos.add(labelGroupListPojo);
        });

        labelGroupListVO.setLabelTree(labelGroupListPojos);


        return labelGroupListVO;
    }

    /**
     * 创建默认分组
     * @param userId
     * @param corpid
     * @param appId
     * @param formId
     * @return
     * @throws XbbException
     */
    @Override
    public LabelGroupEntity createDefaultLabelGroup(String userId, String corpid, Long appId, Long formId) throws XbbException {
        // // 给表单添加默认标签分组
        LabelGroupEntity labelGroupEntity = new LabelGroupEntity();
        labelGroupEntity.setId(null);
        labelGroupEntity.setCorpid(corpid);
        labelGroupEntity.setAppId(appId);
        labelGroupEntity.setFormId(formId);
        labelGroupEntity.setBusinessType(getBusinessType(corpid, appId, formId));
        labelGroupEntity.setGroupName(I18nMessageUtil.getMessage(PaasConstant.DEFAULT_LABEL_GROUP));
        labelGroupEntity.setSort(BasicConstant.ONE);
        labelGroupEntity.setCreatorId(userId);
        try {
            labelGroupModel.save(labelGroupEntity);
        } catch (XbbException e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return labelGroupEntity;
    }

    private Integer getBusinessType(String corpid, Long appId, Long formId) {
        Integer businessType =0 ;
        PaasAppEntity appEntity = paasAppModel.getByKey(appId, corpid);
        if (Objects.equals(appEntity.getAlias(), XbbRefTypeEnum.WORK_ORDER.getAlias())){
            businessType = XbbRefTypeEnum.WORK_ORDER.getCode();
        } else{
            PaasFormEntityExt formEntityExt = paasFormModel.getByKey(formId, corpid);
            businessType = formEntityExt.getBusinessType();
        }
        return businessType;
    }


    /**
     * 分组保存
     * @param labelGroupSaveDTO
     * @return
     * @throws XbbException
     */
    @Override
    public LabelGroupSaveVO saveLabelGroup(LabelGroupSaveDTO labelGroupSaveDTO) throws XbbException {
        Long id = labelGroupSaveDTO.getId();
        Long appId = labelGroupSaveDTO.getAppId();
        Long formId = labelGroupSaveDTO.getFormId();
        String name = labelGroupSaveDTO.getName();
        if (Objects.equals(id, 0L) && name.contains(",")){
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120011);
        }
        if (Objects.equals(name, I18nMessageUtil.getMessage(MessageConstant.LABEL_NAME_RECYCLE))){
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120001);
        }
        String corpid = labelGroupSaveDTO.getCorpid();
        String loginUserName = labelGroupSaveDTO.getLoginUserName();

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("appId", appId);
        param.put("formId", formId);
        param.put("del", 0);
        param.put("name", name);
        if (id > 0){
            param.put("negId", id);
        }
        Integer count = labelGroupModel.getEntitysCount(param);

        if (count> 0){
            throw  new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120001);
        }

        param.clear();
        param.put("corpid", corpid);
        param.put("appId", appId);
        param.put("formId", formId);
        param.put("del", 0);
        count = labelGroupModel.getEntitysCount(param);
        if (Objects.equals(id, 0L) && count >= BasicConstant.LABEL_GROUP_SIZE) {
            // 新增标签分组时 且 标签分组数量大于等于限制数量
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120022);
        }
        LabelGroupEntity labelGroupEntity = new LabelGroupEntity();
        boolean addFlag = false;
        String oldName = "";
        if (id<=0){
            addFlag = true;
            labelGroupEntity.setCorpid(corpid);
            labelGroupEntity.setAppId(appId);
            labelGroupEntity.setFormId(formId);
            labelGroupEntity.setCreatorId(labelGroupSaveDTO.getUserId());
            labelGroupEntity.setGroupName(name);
            labelGroupEntity.setDel(DelEnum.NORMAL.getDel());
            labelGroupEntity.setSort(count);
            labelGroupEntity.setBusinessType(labelGroupSaveDTO.getBusinessType());
        } else {
            labelGroupEntity = labelGroupModel.getByKey(id, corpid);
            if (Objects.isNull(labelGroupEntity)){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
            }
            oldName = labelGroupEntity.getGroupName();
            labelGroupEntity.setGroupName(name);
        }

        LabelGroupSaveVO labelGroupSaveVO = new LabelGroupSaveVO();
        try {
            labelGroupModel.save(labelGroupEntity);
            labelGroupSaveVO.setId(labelGroupEntity.getId());
        } catch (XbbException e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        // 记录日志
        String memo;
        OperateTypeEnum operateTypeEnum;
        if (addFlag) {
            operateTypeEnum = OperateTypeEnum.NEW;
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_FORM_LABEL_GROUP_ADD), loginUserName, name);
        } else {
            operateTypeEnum = OperateTypeEnum.EDIT;
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_FORM_LABEL_GROUP_UPDATE), loginUserName, name, oldName, name);
        }
        mongoLogHelp.buildLog(corpid, labelGroupSaveDTO.getUserId(), loginUserName, OperateModuleTypeEnum.LABEL_GROUP_SET, operateTypeEnum, id.toString(), name, memo, labelGroupSaveDTO.getHttpHeader());
        return labelGroupSaveVO;
    }

    /**
     * 分组删除
     * @param labelGroupDeleteDTO
     * @return
     * @throws XbbException
     */
    @Override
    public LabelGroupDeleteVO deleteLabelGroup(LabelGroupDeleteDTO labelGroupDeleteDTO) throws XbbException {

        Long groupId = labelGroupDeleteDTO.getId();
        String corpid = labelGroupDeleteDTO.getCorpid();
        LabelGroupEntity labelGroupEntity = labelGroupModel.getByKey(groupId, corpid);
        if (Objects.isNull(labelGroupEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }
        List<LabelEntity> labelEntities = labelModel.getByGroupId(groupId, corpid);
        List<Long> labelIds = new ArrayList<>();
        labelEntities.forEach(item -> {
            labelIds.add(item.getId());
        });

        // 删除分类
        try {
            if (CollectionsUtil.isNotEmpty(labelIds)) {
                checkDelteLabel(labelIds, corpid, labelEntities);
            }


            labelGroupModel.deleteBykey(groupId, corpid);

            if (CollectionsUtil.isNotEmpty(labelEntities)) {
                // 原先分类下的标签enable置为1
                labelEntities.forEach(item -> item.setEnable(1));
                labelModel.updateBatch(labelEntities, corpid);
            }
        } catch (XbbException e){
            throw e;
        }catch (Exception e) {
            LOG.error(" 标签删除修改出错 ");
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        // 记录日志
        String userName = labelGroupDeleteDTO.getLoginUserName();
        String name = labelGroupDeleteDTO.getLoginUserName();
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_FORM_LABEL_GROUP_DELETE), userName, name);
        mongoLogHelp.buildLog(corpid, labelGroupDeleteDTO.getUserId(), userName, OperateModuleTypeEnum.LABEL_GROUP_SET, OperateTypeEnum.DELETE, groupId.toString(), name, memo, labelGroupDeleteDTO.getHttpHeader());

        LabelGroupDeleteVO labelGroupDeleteVO = new LabelGroupDeleteVO();
        labelGroupDeleteVO.setGroupId(groupId);

        return labelGroupDeleteVO;
    }

    private void checkDelteLabel(List<Long> labelIds, String corpid, List<LabelEntity> labelEntities) throws XbbException {
        Map<Long, String> id2Name = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        labelEntities.forEach(item->{
            id2Name.put(item.getId(), item.getName());
        });
        PaasFormExplainEntity explainEntity = new PaasFormExplainEntity();
        if (Objects.equals(labelEntities.get(0).getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
            WorkOrderExplainEntityExt workOrderExplainModelByFormId = workOrderExplainModel.getByFormId(labelEntities.get(0).getFormId(), corpid);
            BeanUtil.copyProperties(workOrderExplainModelByFormId, explainEntity);
        } else {
            explainEntity = paasFormExplainModel.getByFormId(labelEntities.get(0).getFormId(), corpid);
        }
        List<FieldAttrEntity> fieldAttrEntities = JSONArray.parseArray(explainEntity.getExplains(), FieldAttrEntity.class);

        FieldAttrEntity fieldAttrEntity = new FieldAttrEntity();
        for (FieldAttrEntity item : fieldAttrEntities) {
            if (Objects.equals(item.getFieldType(), FieldTypeEnum.LABEL.getType())) {
                fieldAttrEntity= item;
                break;
            }
        }
        List<Long> defaultLabelIds = new ArrayList<>();
        DefaultAttrPoJo defaultAttr = fieldAttrEntity.getDefaultAttr();
        if (Objects.nonNull(defaultAttr.getDefaultValue())) {
            Object defaultValue1 = defaultAttr.getDefaultValue();
            if (defaultValue1 instanceof JSONArray){
                JSONArray defaultValue = (JSONArray) defaultValue1;
                for (Object o : defaultValue) {
                    if (o instanceof JSONObject){
                        JSONObject jsonObject = (JSONObject)o;
                        defaultLabelIds.add(jsonObject.getLong("id"));
                    } else {
                        defaultLabelIds.add(Long.parseLong(o.toString()));
                    }
                }
            }
        }
        StringBuilder stringBuilder = new StringBuilder();

        defaultLabelIds.retainAll(labelIds);
        defaultLabelIds.forEach(item->{
            stringBuilder.append(id2Name.get(item)).append("  ");
        });
        if (defaultLabelIds.size()>0){
            LOG.error("标签被设置为默认值,不能删除");
            throw new XbbException(SystemLabelErrorCodeEnum.API_ERROR_1120016 ,String.format(SystemLabelErrorCodeEnum.API_ERROR_1120016.getMsg(), stringBuilder.toString()));
        }
    }

    /**
     * 分组排序
     * @param labelGroupSortDTO
     * @return
     * @throws XbbException
     */
    @Override
    public LabelGroupSortVO sortLabelGroup(LabelGroupSortDTO labelGroupSortDTO) throws XbbException {
        List<LabelSortPojo> sortArray = labelGroupSortDTO.getSortArray();
        Map<Long, Long> sortMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> idIn = new ArrayList<>();
        for (LabelSortPojo pojo : sortArray) {
            Long id = pojo.getId();
            Long sort = pojo.getSort();
            sortMap.put(id, sort);
            idIn.add(id);
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("idIn", idIn);
        param.put("corpid", labelGroupSortDTO.getCorpid());
        param.put("del", 0);
        try {
            if (!sortMap.isEmpty()) {
                labelGroupModel.sortCategory(param, sortMap);
            }
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        LabelGroupSortVO labelGroupSortVO = new LabelGroupSortVO();
        labelGroupSortVO.setIds(idIn);

        return labelGroupSortVO;
    }

    @Override
    public LabelGroupRepeatVO repeatGroup(LabelGroupRepeatDTO labelGroupRepeatDTO) throws XbbException {
        Long groupId = labelGroupRepeatDTO.getGroupId();
        LabelGroupRepeatVO labelGroupRepeatVO = new LabelGroupRepeatVO();
        LabelGroupEntity byKey = labelGroupModel.getByKey(groupId, labelGroupRepeatDTO.getCorpid());
        if (Objects.isNull(byKey)){
            labelGroupRepeatVO.setRepeat(1);
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("appId", labelGroupRepeatDTO.getAppId());
            param.put("formId", labelGroupRepeatDTO.getFormId());
            param.put("corpid", labelGroupRepeatDTO.getCorpid());
            param.put("del", DelEnum.NORMAL.getDel());
            List<LabelGroupEntity> entitys = labelGroupModel.findEntitys(param);
            labelGroupRepeatVO.setLabelGroupEntities(entitys);
        }else {
            labelGroupRepeatVO.setRepeat(0);
        }
        return labelGroupRepeatVO;
    }

}
